import axios from 'axios'
import { message } from 'ant-design-vue'
import { errMessage } from './errorCode'
import { deleteAccessToken, getAccessToken, setAccessToken } from '@/utils/auth'

/**
 * 默认请求类型
 */
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'

const service = axios.create({
  baseURL: import.meta.env.VITE_BASE_API,
  timeout: 15000
})

/**
 * 请求拦截器
 */
service.interceptors.request.use(
  config => {
    const token = getAccessToken()
    if (token) {
      config.headers['Authorization'] = `Bearer ${token}`
    }
    return config
  },
  error => Promise.reject(error)
)

/**
 * 响应拦截器
 */
service.interceptors.response.use(
  res => {
    const { code, msg, repCode } = res.data

    // 刷新 token
    if (
      res.headers?.getAuthorization() &&
      res.headers?.getAuthorization() !== `Bearer ${getAccessToken()}`
    ) {
      deleteAccessToken()
      setAccessToken(res.headers?.getAuthorization().replace('Bearer ', ''))
    }

    if (code !== 200 && !repCode) {
      message.error({
        content: msg || errMessage(code),
        duration: 2,
        onClose: () => {
          // 如果是认证失败，清除 token 并跳转登录页
          if (code === 401) {
            getAccessToken() && deleteAccessToken()
            location.reload()
            return
          }
        }
      })

      return Promise.reject(new Error(msg || errMessage(code)))
    }

    return res.data
  },
  err => {
    let messageContent = ''

    if (err.message === 'Network Error') {
      messageContent = '后端接口连接异常'
    } else if (err.message.includes('timeout')) {
      messageContent = '系统接口请求超时'
    } else if (err.message.includes('Request failed with status code')) {
      messageContent = `系统接口${err.message.slice(-3)}异常`
    } else {
      messageContent = '未知错误'
    }

    message.error(messageContent)
    return Promise.reject(err)
  }
)

/**
 * 各类型请求封装
 */
export default {
  get: async <T = any>(option: any) => {
    const res = await service({ method: 'GET', ...option })
    return res.data as unknown as T
  },

  post: async <T = any>(option: any) => {
    const res = await service({ method: 'POST', ...option })
    return res.data as unknown as T
  },

  postOriginal: async (option: any) => {
    return await service({ method: 'POST', ...option })
  },

  delete: async <T = any>(option: any) => {
    const res = await service({ method: 'DELETE', ...option })
    return res.data as unknown as T
  },

  put: async <T = any>(option: any) => {
    const res = await service({ method: 'PUT', ...option })
    return res.data as unknown as T
  },

  download: async <T = any>(option: any) => {
    const res = await service({ method: 'GET', responseType: 'blob', ...option })
    return res as unknown as Promise<T>
  },

  upload: async <T = any>(option: any) => {
    option.headersType = 'multipart/form-data'
    const res = await service({ method: 'POST', ...option })
    return res as unknown as Promise<T>
  }
}
